package com.fudan.backend.service.impl;

import com.fudan.backend.dao.BillDao;
import com.fudan.backend.dao.UserDao;
import com.fudan.backend.exception.BaseException;
import com.fudan.backend.exception.RetCode;
import com.fudan.backend.pojo.Bill;
import com.fudan.backend.pojo.Store;
import com.fudan.backend.pojo.User;
import com.fudan.backend.pojo.statics.AccountStatic;
import com.fudan.backend.service.BillService;
import com.fudan.backend.service.StoreService;
import com.fudan.backend.util.Snowflake;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class BillServiceImpl implements BillService {
    @Autowired
    BillDao billDao;
    @Autowired
    UserDao userDao;
    @Autowired
    StoreService storeService;
    @Autowired
    Snowflake snowflake;

    @Override
    public String addBill(String sendAccountId, String receiveAccountId, Double amount, Integer type, String moreInfo) {
        String id = snowflake.nextId().toString();
        Bill bill = new Bill(id, sendAccountId, receiveAccountId,
                amount, new Date(System.currentTimeMillis()), type, moreInfo);
        billDao.addBill(bill);
        return id;
    }

    @Override
    public List<Bill> getAllBillByAccountIdAndDays(String accountId, Integer days) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.DATE, -days);
        Date before = calendar.getTime();
        return billDao.getBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public List<Bill> getIncomeBillByAccountIdAndDays(String accountId, Integer days) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.DATE, -days);
        Date before = calendar.getTime();
        return billDao.getReceiveBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public List<Bill> getOutBillByAccountIdAndDays(String accountId, Integer days) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.DATE, -days);
        Date before = calendar.getTime();
        return billDao.getSendBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public List<Bill> getAllBillByAccountIdAndMonths(String accountId, Integer months) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.MONTH, -months);
        Date before = calendar.getTime();
        return billDao.getBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public List<Bill> getIncomBillByAccountIdAndMonths(String accountId, Integer months) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.MONTH, -months);
        Date before = calendar.getTime();
        return billDao.getReceiveBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public List<Bill> getOutBillByAccountIdAndMonths(String accountId, Integer months) {
        Calendar calendar = new GregorianCalendar();
        Date current = new Date(System.currentTimeMillis());
        calendar.setTime(current);
        calendar.add(Calendar.MONTH, -months);
        Date before = calendar.getTime();
        return billDao.getSendBillByAccountIdTime(accountId, before, current);
    }

    @Override
    public PageInfo<Bill> getAllBillPageByAccountId(String accountId, Integer current, Integer size) {
        PageHelper.startPage(current, size);
        List<Bill> list = billDao.getBillByAccountId(accountId);
        return new PageInfo<>(list);
    }

    @Override
    public PageInfo<Bill> getLastMonthBillPageByAccountId(String accountId, Integer current, Integer size) {
        PageHelper.startPage(current, size);
        List<Bill> list = this.getAllBillByAccountIdAndMonths(accountId, 1);
        return new PageInfo<>(list);
    }

    @Override
    public PageInfo<Bill> getLastWeekBillPageByAccountId(String accountId, Integer current, Integer size) {
        PageHelper.startPage(current, size);
        List<Bill> list = this.getAllBillByAccountIdAndDays(accountId, 7);
        return new PageInfo<>(list);
    }

    @Override
    public PageInfo<Bill> getAllBillPageByUserId(String userId, Integer current, Integer size) {
        User user = userDao.selectUserByUserId(userId);
        if (user == null) {
            throw new BaseException(RetCode.USER_ID_NOT_FOUND);
        }
        return this.getAllBillPageByAccountId(user.getAccountId(), current, size);
    }

    @Override
    public PageInfo<Bill> getLastMonthBillPageByUserId(String userId, Integer current, Integer size) {
        User user = userDao.selectUserByUserId(userId);
        if (user == null) {
            throw new BaseException(RetCode.USER_ID_NOT_FOUND);
        }
        return this.getLastMonthBillPageByAccountId(user.getAccountId(), current, size);
    }

    @Override
    public PageInfo<Bill> getLastWeekBillPageByUserId(String userId, Integer current, Integer size) {
        User user = userDao.selectUserByUserId(userId);
        if (user == null) {
            throw new BaseException(RetCode.USER_ID_NOT_FOUND);
        }
        return this.getLastWeekBillPageByAccountId(user.getAccountId(), current, size);
    }

    @Override
    public PageInfo<Bill> getAllBillPageByStoreId(String storeId, String userId, Integer current, Integer size) {
        Store store = storeService.checkStoreAuthorize(storeId, userId);
        return this.getAllBillPageByAccountId(store.getAccountId(), current, size);
    }

    @Override
    public PageInfo<Bill> getLastMonthBillPageByStoreId(String storeId, String userId, Integer current, Integer size) {
        Store store = storeService.checkStoreAuthorize(storeId, userId);
        return this.getLastMonthBillPageByAccountId(store.getAccountId(), current, size);
    }

    @Override
    public PageInfo<Bill> getLastWeekBillPageByStoreId(String storeId, String userId, Integer current, Integer size) {
        Store store = storeService.checkStoreAuthorize(storeId, userId);
        return this.getLastWeekBillPageByAccountId(store.getAccountId(), current, size);
    }

    @Override
    public Double calBillsAmount(List<Bill> billList) {
        double total = 0.0;
        for (Bill bill : billList) {
            total += bill.getBillAmount();
        }
        return total;
    }

    @Override
    public Map<String, Object> calUserStatistic(String userId, int type) {
        User user = userDao.selectUserByUserId(userId);
        if (user == null) {
            throw new BaseException(RetCode.USER_ID_NOT_FOUND);
        }
        String accountId = user.getAccountId();
        return this.genStatisticMap(accountId, type);
    }

    @Override
    public Map<String, Object> calStoreStatistic(String storeId, String userId, int type) {
        Store store = storeService.checkStoreAuthorize(storeId, userId);
        String accountId = store.getAccountId();
        return this.genStatisticMap(accountId, type);
    }

    @Override
    public Map<String, Object> calWebshopStatistic(int type) {
        return this.genStatisticMap(AccountStatic.WEBSHOP_ACCOUNT_ID, type);
    }

    /**
     * 计算流水支出与入账
     *
     * @param type 0近一个周，1近一个月，2全部
     * @return map包含 income， expend
     */
    private Map<String, Object> genStatisticMap(String accountId, int type) {
        List<Bill> billIncomList;
        List<Bill> billSendList;
        switch (type) {
            case 0: //近一周
                billIncomList = this.getIncomeBillByAccountIdAndDays(accountId, 7);
                billSendList = this.getOutBillByAccountIdAndDays(accountId, 7);
                break;
            case 1://近一月
                billIncomList = this.getIncomBillByAccountIdAndMonths(accountId, 1);
                billSendList = this.getOutBillByAccountIdAndMonths(accountId, 1);
                break;
            case 2://所有
                billIncomList = billDao.getReceiveBillByAccountId(accountId);
                billSendList = billDao.getSendBillByAccountId(accountId);
                break;
            default:
                throw new BaseException(RetCode.INVALID_REQUEST);
        }
        double income = this.calBillsAmount(billIncomList);
        double expend = this.calBillsAmount(billSendList);
        Map<String, Object> map = new HashMap<>();
        map.put("income", income);
        map.put("expend", expend);
        return map;
    }

}
